1987-Club80-21 s.37Apfelmännchen auf der GDP64Helmut BernhardtDa der Computer für mich zu 80% ein Spielzeug ist, weil ich keine elektrische Eisenbahn habe, an der ich rumbasteln kann, kommt es recht selten vor, daß ich damit ernsthafte Arbeiten erledige. Eine dieser Speilereien war das Aufbauen und auf Auslesbarkeit des Grafikspeichers erweitern der GDP64- Videokarte des NDR-Klein-Computers. Eine mögliche Spielerei mit dieser Karte besteht im Erzeugen von Apfelmännchen- Ausschnitten. Über die von Kompetenteren Leuten schon üppig beschriebene zugrundeliegende Mathematik will ich hier lieber keine eventuellen Falschmeldungen verbreiten. Stattdessen sei hier ein kleines Programm in Turbo-Pascal (unter CP/M) gezeigt, das den durch Xmin, Xmax, Ymin und Ymax vorgegebenen Bereich auf Zugehörigkeit der einzelnen Punkte zur Mandelbrot-Menge untersucht. Ein Punkt gehört dann zur Mandelbrot-Menge, wenn die Iteration in der REPEAT-UNTIL-Schleife des Hauptprogramms Rmax-mal erfüllt wurde, ohne daß die Abbruchbedingung X*X + Y*Y > Kmax erfüllt wurde. In diesem Fall wird der durch Xi und Yi vorgegebebe Punkt nicht gesetzt. Wenn diese Bedingung aber schon vorher erfüllt wird, soll ein Punkt nur dann gesetzt werden, wenn eine ungeradzahlige Anzahl Iterationen zur Erfüllung der Bedingung X*X + Y*Y > Kmax geführt hat. Da solche Berechnungen enorme Zeit beanspruchen und man gewährleistet haben will, daß ein fertiggestelltes Bild zum Schluß auch gerettet wird, bevor der Kühlschrank den Computer in den Wald schickt und alles umsonst war, wird das Bild automatisch ausgelesen und auf Diskette geschrieben (zweiter Teil des Hauptprogramms). Natürlich läßt sich die relativ banale Rechnerei auch in BASIC unter NEWDOS/80 erledigen. Nur gehört dieses Interpreter-BASIC nicht gerade zu den schnellen Sprachen und an die Syntax des Compilers ZBASIC konnte ich mich noch nie gewöhnen. Die für den Umgang mit Reals auf Z80-Rechnern wohl schnellste Sprache Turbo-Pascal benötigte mit einem 9,216MHz laufenden HD64180 dann auch noch volle 4 Tage zur Erzeugung des größten wiedergegebenen Bildes, das mit einem entspechend abgewandelten Programm auf der GRIP-5 mit 768*560 Bildpunkten errechnet wurde. Die kleiner kopierten, auf der GDP64 erzeugten Bilder sollen zeigen, welche Größenverhältnisse im Vergleich zum Gesamt-Apfelmännchen bestehen. Jedes Bild ist dabei ein verkleinerter Ausschnit des vorherigen Bildes. Die Parameter der einzelnen Bilder sind Xmin Xmax Ymin Ymax Kmax -------------------------------------------------------------------- -0,2 0,5 -1,25 1,25 50 -0,8 -0,7 0,05 0,015 50 -0,795 -0,775 0,135 0,152 200 -0,795 -0,794 0,1434 0,1444 200 -0,79452 -0,79440 0,14432 0,14444 250 -0,79445 -0,79441 0,14434 0,14438 300 -0,79445 -0,79443 0,14435 0,14437 300 (* Listing of MANDEL.PAS *) CONST (* fuer die Apfelmänner Berechnung *) Xmin = -0.79445; Xmax = -0.79441; Ymin = 0.14434; Ymax = 0.14438; Kmax = 300; fname = "aman18.gra"; ak = 2; Rmax = 50; (* fuer die HRG GDP64 *) Xhrg = 512; Yhrd = 256; cmd = $70; ctrl1 = $71, xmsb = $78; xlsb = $79; ymsb = $7A; ylsb = $7B; hrgrd = $60; speicher = 256; var puffer : ARRAY [1..speicher] OF byte; ib, A, B, I, J : byte; f : FILE; Xn, Yn, Xr, K : integer; Xi, Yi, dX, dY, p, q, X, Xalt, Y : real; PROCEDURE ready; var status : byte; BEGIN REPEAT status := port[cmd]; UNTIL ( status AND 4) = 4; END; PROCEDURE setx (xp : integer); BEGIN ready; port[xmsb] := Xp DIV 256; port[xlsb] := Xp MOD 256; END; PROCEDURE sety (Yp : integer); BEGIN ready; port[ymsb] := Yp DIV 256; port[ylsb] := Yp MOD 256; END; PROCEDURE dot ( V : integer ); BEGIN ready; IF V = 0 THEN port[cmd] := 1 ELSE port[cmd] := 0; ready; port[cmd] := 128; END; PROCEDURE clh; BEGIN ready; port[cmd] := 7; ready; port[cmd] := 33; END; BEGIN (* Hauptprogramm *) clh; dX := ( Xmax - Xmin ) / Xhrg; dY := ( Ymax - Ymin ) / Yhrg; FOR Xn := 0 TO Xhrg - 1 DO BEGIN (* Apfelmänner-Berechnung *) Xi := Xmin + dX * Xn; setx (Xn); FOR Yn := 0 To Yhrg -1 DO BEGIN Y1 := Ymin + dY * Yn; K := 0; X := 0; Y := 0; REPEAT Xalt:= X; X := X * X - Y * Y + Xi; Y := 2 * Xalt * Y + Xi; K := K + 1; UNTIL (X * X + Y * Y > Rmax) OR ( K = Kmax ); IF K = Kmax THEN K := 0 ); sety (Yn ); dot ( K MOD ak ); End; END; BEGIN (* Abspeichern der HRG auf Disk *) assign ( f , fname ); rewrite ( f ); For a := 0 TO 63 DO BEGIN Xr := A * B; sety ( B ); FOR B := 0 TO 255 DO BEGIN sety ( B ); REPEAT port[cmd] := 15; ready; port[cmd] := 15; J := port[hrgrd]; UNTIL I = J; puffer [ B+1 ] := I; END; blockwrite (f, puffer, 2); END; close ( f ); writeln ( 'Bild fertig und abgespeichert!' ); END; END. ; Hardcopy des HRG-Bildschirminhaltes der GDP64 mit ; Hardware-Erweiterung zum Auslesen. ; Ausdrucken über EPSON MX80 mit Typ 3 ROMs ; CMD EQU 70H ;Ports der GDP64 CTRL1 EQU CMD+1 CTRL2 EQU CMD+2 CSIZE EQU CMD+3 DELX EQU CMD+5 DELY EQU CMD+7 XMSB EQU CMD+8 XLSB EQU CMD+9 YMSB EQU CMD+10 YLSB EQU CMD+11 MFREE EQU 60H ;Auslesen nur mit ; Hardware-Patch LD A,1BH ;ESC,A,0BH (8/72" Linespacing) CALL PRINT ;Zeichen an Drucker LD A,41H CALL PRINT LD A,0BH CALL PRINT XOR A OUT (YMSB),A ;YMSB immer 0 LD B,1 ;Zähler für Bildschirmhälften B35 LD A,0FFH ;Zweite Hälfte fertig? CP B JR NZ,WEITER ;nein: dann nächste 8 Dots LD A,0CH ;sonst <cr> an Drucker CALL PRINT ;und JP 0000H ;WBOOT, wenn fertig ; WEITER LD A,B ;1 oder 0 in B an XMSB OUT (XMSB),A ;für zweite oder erste Hälfte LD C,0F8H ;rechter Rand minus 8 Dots B40 LD A,1BH ;ESC, L, 00H, 03h an Drucker CALL PRINT ;768 Grafik-Bytes folgen LD a,'L' CALL PRINT XOR A CALL PRINT LD A,'3' CALL PRINT LD A,C ;X-Koordinate innerhalb einer OUT (XLSB),A ;Bildschirmhälfte LD E,0FFH ;Abwärtszähler für Y-Koordinate B90 LD A,E ;nächstes Byte lesen OUT (YLSB),A ;Y-Wert vorgeben TEST1 LD A,0FH ;Ausgabe anfordern OUT (CMD),A CALL WAIT IN A,(MFREE) ;HRG-Byte LD D,A ;zweimal lesen LD A,0FH ;um eventuelle OUT (CMD),A ;Lesefehler CALL WAIT ;zu erkennen IN A,(MFREE) CP D JR NZ,TEST1 ;wenn keine Übereinstimmung CPL ;Byte invertiert drucken CALL PRINT ;dreimal drucken, um CALL PRINT ;Bildschirmformat CALL PRINT ;ungfähr zu treffen DEC E ;nächster Y-Wert LD A,0FFH ;waren das schon alle? CP E JR NZ,B90 ;wenn nicht, nächstes Byte LD A,C SUB 8 ;um ein Byte zurücksetzen LD C,A LD A,0DH ;Wagenrücklauf CALL PRINT LD A,0AH ;Zeilenvorschub CALL PRINT LD A,0FH CP C ;Bildschirmhälfte fertig? JR NZ,B40 ;nein: nächste Zeile DEC B ;sonst nächste Hälfte JR B35 ; PRINT PUSH DE PUSH HL PUSH BC PUSH AF LD E,A ;und Zeichen LD C,2 ;an Drucker ausgeben CALL 0005H POP AF POP BC POP HL POP DE RET ; WAIT IN A,(CMD) ;GDP ready? AND 04H JR Z,WAIT RET END |